/**
 * @copyright Copyright (c) 2021 Oray Inc. All rights reserverd.
 * No Part of this file may be reproduced, stored
 * in a retrieval system, or transmitted, in any form, or by any means,
 * electronic, mechanical, photocopying, recording, or otherwise,
 * without the prior consent of Oray Inc.
 * 
 * @file template_thread.hpp
 * @author sunchao (sunchao@oray.com)
 * @brief 线程模板
 * @version 0.1
 * @date 2021-09-16
 */
#ifndef _TEMPLATE_THREAD_H
#define _TEMPLATE_THREAD_H
#include <thread> 
#include <mutex>
#include <unistd.h>
#include <assert.h>
#include <sys/syscall.h>
#include <sys/prctl.h>



/**
 * @brief 模板线程
 *      \li 需要绑定一个类和该类的一个非静态函数指针
 *      \li 非静态函数不可阻塞，在无处理情况下建议等待一段时间后在返回
 * 
 * @tparam T 绑定的类
 */
template<typename T>
class template_thread
{
public:
    template_thread() : mutex_()
    {

    }

    ~template_thread()
    {
        //printf("~template_thread()~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
    }
    /**
     * @brief 线程启动
     * 
     * @param thread_name 线程名称
     * @param t 绑定的类
     * @param thread_cb 绑定类的非静态函数指针
     * @return true 启动成功
     * @return false 启动失败
     */
    bool start(const char *thread_name, T *t, void (T::*thread_cb)())
    {
        std::lock_guard<std::mutex> lock(mutex_);
        thread_name_ = thread_name;
        is_close_ = false;
        need_exit_ = false;

        pthread_ = new std::thread(template_thread::dispose, this, t, thread_cb);
        if( pthread_ == NULL )
        {
            close();
            return false;
        }

        return true;
    }

    /**
     * @brief 获取OS线程ID 线程外部调用则获取到调用线程的ID
     * 
     * @return pid_t 线程ID
     */
    pid_t gettid()
    {
        return syscall(SYS_gettid);    
    }

    /**
     * @brief 线程是否关闭
     * 
     * @return true 已关闭
     * @return false 未关闭
     */
    bool is_close()
    {
        bool is_close = true;
        {
            std::lock_guard<std::mutex> lock(mutex_);
            is_close = is_close_;
        }
        return is_close;
    }

    /**
     * @brief 线程关闭
     * 
     */
    void close()
    {
        if ( is_close_ )
            return;

        {
            std::lock_guard<std::mutex> lock(mutex_);
            is_close_ = true;
            need_exit_ = false;
        }
        
        if( pthread_ != NULL )
        {
            pthread_->join();
            delete pthread_;
            pthread_ = NULL;
            
        }
    }

    void exit()
    {
        {
            std::lock_guard<std::mutex> lock(mutex_);
            need_exit_ = true;
        }
    }

    bool is_exit()
    {
        bool is_exit = true;
        {
            std::lock_guard<std::mutex> lock(mutex_);
            is_exit = need_exit_;
        }
        return is_exit;
    }


    /**
     * @brief 心跳扩展（等待后续开发）
     * 
     */
    void alive()
    {
        //用于后期做线程看护使用
    }

    /**
     * @brief 线程处理流程
     *      \li 不可在外部调用
     * 
     * @param pthread 线程句柄
     * @param t  绑定的类
     * @param thread_cb 绑定类的非静态函数指针
     */
    static void dispose(template_thread *pthread, T *t, void (T::*thread_cb)())
    {
        prctl(PR_SET_NAME, pthread->thread_name_.c_str()); //更改线程名字
        printf("template_thread:[%s] tid:[%d]\n", pthread->thread_name_.c_str(), pthread->gettid());
        
        do
        {
            if ( pthread->is_exit() )
                return;
            
            (t->*thread_cb)();
            pthread->alive();
        }   while ( !pthread->is_close() );

    }

public:
    std::string thread_name_ = "";

private:
    template_thread(const template_thread& rhs);
    template_thread& operator = (const template_thread& rhs);
    
private:
    mutable std::mutex mutex_;
    std::thread *pthread_ = NULL;

    bool is_close_ = true;
    bool need_exit_ = false;
    
};


#endif //_TEMPLATE_THREAD_H
